/*
 Navicat MySQL Data Transfer

 Source Server         : root
 Source Server Type    : MySQL
 Source Server Version : 80015
 Source Host           : localhost:3306
 Source Schema         : community

 Target Server Type    : MySQL
 Target Server Version : 80015
 File Encoding         : 65001

 Date: 11/04/2020 13:02:44
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for collection
-- ----------------------------
DROP TABLE IF EXISTS `collection`;
CREATE TABLE `collection` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `question_id` int(11) NOT NULL,
  `gmt_create` bigint(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

-- ----------------------------
-- Records of collection
-- ----------------------------
BEGIN;
INSERT INTO `collection` VALUES (9, 18, 55, 1581155157943);
INSERT INTO `collection` VALUES (13, 21, 55, 1581493810494);
INSERT INTO `collection` VALUES (14, 18, 53, 1581667364178);
COMMIT;

-- ----------------------------
-- Table structure for comment
-- ----------------------------
DROP TABLE IF EXISTS `comment`;
CREATE TABLE `comment` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `parent_id` bigint(20) NOT NULL COMMENT '父类id',
  `type` int(2) NOT NULL COMMENT '父类类型Type未1表示评论的问题，type为2表示回复的评论',
  `commentator` int(10) NOT NULL COMMENT '评论人id',
  `gmt_create` bigint(255) NOT NULL COMMENT '创建时间',
  `gmt_modified` bigint(255) NOT NULL COMMENT '修改时间',
  `like_count` bigint(255) DEFAULT '0' COMMENT '点赞数',
  `content` varchar(255) COLLATE utf8_bin NOT NULL COMMENT '评论',
  `comment_count` int(255) DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1228552372695961603 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

-- ----------------------------
-- Records of comment
-- ----------------------------
BEGIN;
INSERT INTO `comment` VALUES (1, 1162606688435269633, 2, 18, 1566022009361, 1566022009361, 0, '数据库', 0);
INSERT INTO `comment` VALUES (1162606688435269633, 3, 1, 18, 1566022009361, 1566022009361, 0, '这是一条测试评论,评论的是id为3的问题', 1);
INSERT INTO `comment` VALUES (1162624962644504577, 42, 1, 18, 1566026366277, 1566026366277, 0, '测试评论', 1);
INSERT INTO `comment` VALUES (1162644196242059266, 42, 1, 18, 1566030951924, 1566030951924, 0, '第二条测试评论', 0);
INSERT INTO `comment` VALUES (1162644233969823745, 42, 1, 18, 1566030960918, 1566030960918, 0, '第三条测试评论', 0);
INSERT INTO `comment` VALUES (1162648042074894337, 47, 1, 18, 1566031868843, 1566031868843, 0, '刚才试了下，没啥影响', 0);
INSERT INTO `comment` VALUES (1162649445094748162, 42, 1, 18, 1566032203348, 1566032203348, 0, ' ', 0);
INSERT INTO `comment` VALUES (1162665233914634242, 47, 1, 18, 1566035967688, 1566035967688, 0, '测试评论', 0);
INSERT INTO `comment` VALUES (1162665764263403521, 7, 1, 18, 1566036094140, 1566036094140, 0, '1', 3);
INSERT INTO `comment` VALUES (1162666084804698113, 7, 1, 18, 1566036170562, 1566036170562, 0, '2', 0);
INSERT INTO `comment` VALUES (1162666153150881793, 1162666084804698113, 2, 18, 1566036186859, 1566036186859, 0, '2', 0);
INSERT INTO `comment` VALUES (1162668482281447425, 1162666084804698113, 2, 18, 1566036742167, 1566036742167, 0, '1', 0);
INSERT INTO `comment` VALUES (1162668524266430465, 1162666084804698113, 2, 18, 1566036752178, 1566036752178, 0, '3', 0);
INSERT INTO `comment` VALUES (1162670364798328834, 1162665764263403521, 2, 18, 1566037190993, 1566037190993, 0, '1', 0);
INSERT INTO `comment` VALUES (1162671684187955202, 1162665764263403521, 2, 18, 1566037505560, 1566037505560, 0, '2', 0);
INSERT INTO `comment` VALUES (1162671710901477377, 1162665764263403521, 2, 18, 1566037511929, 1566037511929, 0, '3', 0);
INSERT INTO `comment` VALUES (1162671746087493633, 43, 1, 18, 1566037520320, 1566037520320, 0, '1', 0);
INSERT INTO `comment` VALUES (1162671847115694082, 48, 1, 18, 1566037544406, 1566037544406, 0, '1', 0);
INSERT INTO `comment` VALUES (1162671857936998402, 48, 1, 18, 1566037546986, 1566037546986, 0, '2', 1);
INSERT INTO `comment` VALUES (1162671871778201601, 1162671857936998402, 2, 18, 1566037550286, 1566037550286, 0, '1', 0);
INSERT INTO `comment` VALUES (1162971314981261314, 47, 1, 18, 1566108943106, 1566108943106, 0, 'test', 0);
INSERT INTO `comment` VALUES (1162971699892539394, 47, 1, 18, 1566109034879, 1566109034879, 0, 'test', 0);
INSERT INTO `comment` VALUES (1162972092852727810, 47, 1, 18, 1566109128561, 1566109128561, 0, 'test', 0);
INSERT INTO `comment` VALUES (1162972447334330369, 4, 1, 18, 1566109213082, 1566109213082, 0, 'test', 0);
INSERT INTO `comment` VALUES (1162972695242862593, 4, 1, 18, 1566109272188, 1566109272188, 0, 'test', 0);
INSERT INTO `comment` VALUES (1162972873614028802, 4, 1, 18, 1566109314715, 1566109314715, 0, 'test', 2);
INSERT INTO `comment` VALUES (1162974501305933826, 1162972873614028802, 2, 18, 1566109702763, 1566109702763, 0, 'test', 0);
INSERT INTO `comment` VALUES (1162986811281956865, 46, 1, 18, 1566112637469, 1566112637469, 0, '1', 1);
INSERT INTO `comment` VALUES (1162986826117210114, 1162986811281956865, 2, 18, 1566112641251, 1566112641251, 0, '1', 0);
INSERT INTO `comment` VALUES (1163001385414647809, 1162972873614028802, 2, 18, 1566116112450, 1566116112450, 0, 'http://localhost:8080/question/4', 0);
INSERT INTO `comment` VALUES (1163004556836966401, 1162606688435269633, 2, 18, 1566116868317, 1566116868317, 0, '1', 0);
INSERT INTO `comment` VALUES (1163035488306343938, 53, 1, 18, 1566124243081, 1566124243081, 0, '哇，超赞的学习笔记～', 0);
INSERT INTO `comment` VALUES (1226419526728450049, 55, 1, 20, 1581236175281, 1581236175281, 0, '蹲一个回复', 0);
INSERT INTO `comment` VALUES (1227495965678690305, 5, 1, 20, 1581492818646, 1581492818646, 0, '1', 1);
INSERT INTO `comment` VALUES (1227499663284822018, 1227495965678690305, 2, 20, 1581493700223, 1581493700223, 0, '1', 0);
INSERT INTO `comment` VALUES (1228552372695961602, 1162624962644504577, 2, 18, 1581744685526, 1581744685526, 0, '.', 0);
COMMIT;

-- ----------------------------
-- Table structure for notification
-- ----------------------------
DROP TABLE IF EXISTS `notification`;
CREATE TABLE `notification` (
  `id` bigint(255) NOT NULL AUTO_INCREMENT,
  `notifier` bigint(255) NOT NULL,
  `receiver` bigint(255) NOT NULL,
  `outerid` bigint(255) NOT NULL,
  `type` int(255) NOT NULL,
  `gmt_create` bigint(255) NOT NULL,
  `status` int(1) NOT NULL DEFAULT '0',
  `notifier_name` varchar(255) COLLATE utf8_bin DEFAULT NULL,
  `outer_title` varchar(255) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `outerid` (`outerid`)
) ENGINE=InnoDB AUTO_INCREMENT=1228552372716933122 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

-- ----------------------------
-- Records of notification
-- ----------------------------
BEGIN;
INSERT INTO `notification` VALUES (1162972873626611713, 18, 18, 4, 1, 1566109314719, 1, 'seagold', 'question test');
INSERT INTO `notification` VALUES (1162986811298734081, 18, 18, 46, 1, 1566112637719, 1, 'seagold', 'JVM虚拟机中GC机制');
INSERT INTO `notification` VALUES (1163001385448202241, 18, 18, 4, 2, 1566116112467, 1, 'seagold', 'http://localhost:8080/question/4');
INSERT INTO `notification` VALUES (1226419526749421569, 20, 18, 55, 1, 1581236175607, 1, NULL, 'MyBatis中@parm注解的使用时机和需要注意什么');
INSERT INTO `notification` VALUES (1227495965691273217, 20, 18, 5, 1, 1581492818649, 0, 'Thanos', '1');
INSERT INTO `notification` VALUES (1227499663297404930, 20, 20, 5, 2, 1581493700227, 1, 'Thanos', '1');
INSERT INTO `notification` VALUES (1228552372716933121, 18, 18, 42, 2, 1581744685711, 0, 'seagold', '测试评论');
COMMIT;

-- ----------------------------
-- Table structure for question
-- ----------------------------
DROP TABLE IF EXISTS `question`;
CREATE TABLE `question` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '标题',
  `description` text CHARACTER SET utf8 COLLATE utf8_bin COMMENT '描述',
  `gmt_create` bigint(255) DEFAULT NULL COMMENT '创建时间',
  `gmt_modified` bigint(255) DEFAULT NULL COMMENT '修改时间',
  `creator` int(20) DEFAULT '0' COMMENT '创建人ID',
  `comment_count` int(10) DEFAULT '0' COMMENT '评论数',
  `view_count` int(10) DEFAULT '0' COMMENT '观看数',
  `like_count` int(10) DEFAULT '0' COMMENT '点赞数',
  `tag` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '标签',
  `head_img` varchar(255) COLLATE utf8_bin DEFAULT NULL,
  `choice` int(1) unsigned zerofill NOT NULL DEFAULT '0' COMMENT '是否为精华',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=57 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

-- ----------------------------
-- Records of question
-- ----------------------------
BEGIN;
INSERT INTO `question` VALUES (3, '测试修改发起的问题', 'wrapper对象怎么实现', 1565873729572, 1565873729572, 18, 1, 29, 0, 'Mybatis', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 0);
INSERT INTO `question` VALUES (4, 'question test', 'test...', 1565874197521, 1565874197521, 18, 3, 33, 0, 'java', 'https://avatars2.githubusercontent.com/u/49060515?v=4)', 0);
INSERT INTO `question` VALUES (5, '1', '1', 1565933170602, 1565933170602, 18, 1, 8, 0, '1', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 0);
INSERT INTO `question` VALUES (6, 'MybatisPlus联合查询', 'wrapper对象怎么实现', 1565873729572, 1565873729572, 18, 0, 5, 0, 'Mybatis', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 0);
INSERT INTO `question` VALUES (7, 'question test', 'test...', 1565874197521, 1565874197521, 18, 2, 29, 0, 'java', 'https://avatars2.githubusercontent.com/u/49060515?v=4)', 0);
INSERT INTO `question` VALUES (33, 'MybatisPlus联合查询', 'wrapper对象怎么实现', 1565873729572, 1565873729572, 18, 0, 6, 0, 'Mybatis', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 0);
INSERT INTO `question` VALUES (34, 'question test', 'test...', 1565874197521, 1565874197521, 18, 0, 0, 0, 'java', 'https://avatars2.githubusercontent.com/u/49060515?v=4)', 0);
INSERT INTO `question` VALUES (35, '1', '1', 1565933170602, 1565933170602, 18, 0, 0, 0, '1', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 0);
INSERT INTO `question` VALUES (36, 'MybatisPlus联合查询', 'wrapper对象怎么实现', 1565873729572, 1565873729572, 18, 0, 0, 0, 'Mybatis', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 0);
INSERT INTO `question` VALUES (37, 'question test', 'test...', 1565874197521, 1565874197521, 18, 0, 1, 0, 'java', 'https://avatars2.githubusercontent.com/u/49060515?v=4)', 0);
INSERT INTO `question` VALUES (38, '1', '1', 1565933170602, 1565933170602, 18, 0, 0, 0, '1', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 0);
INSERT INTO `question` VALUES (39, 'MybatisPlus联合查询', 'wrapper对象怎么实现', 1565873729572, 1565873729572, 18, 0, 1, 0, 'Mybatis', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 0);
INSERT INTO `question` VALUES (40, 'question test', 'test...', 1565874197521, 1565874197521, 18, 0, 0, 0, 'java', 'https://avatars2.githubusercontent.com/u/49060515?v=4)', 0);
INSERT INTO `question` VALUES (41, '1', '1', 1565933170602, 1565933170602, 18, 0, 1, 0, '1', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 0);
INSERT INTO `question` VALUES (42, 'MybatisPlus联合查询', 'wrapper对象怎么实现', 1565873729572, 1565873729572, 18, 4, 131, 0, 'Mybatis', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 0);
INSERT INTO `question` VALUES (43, 'question test', 'test...', 1565874197521, 1565874197521, 18, 1, 11, 0, 'java', 'https://avatars2.githubusercontent.com/u/49060515?v=4)', 0);
INSERT INTO `question` VALUES (44, '1', '1', 1565933170602, 1565933170602, 18, 0, 0, 0, '1', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 0);
INSERT INTO `question` VALUES (45, '测试清除Session登陆', '测试清除Session登陆', 1565952366547, 1565952366547, 18, 0, 2, 0, 'java', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 0);
INSERT INTO `question` VALUES (46, 'JVM虚拟机中GC机制', '是什么？怎么实现的？', 1565958481439, 1565958481439, 18, 1, 7, 0, 'java,intellij-idea', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 0);
INSERT INTO `question` VALUES (47, 'Mysql数据库主键从int变为Long', '是否有bug产生，主键自增有什么影响?', 1566022246358, 1566022246358, 18, 5, 142, 0, 'java,mysql,Mybatis', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 0);
INSERT INTO `question` VALUES (52, '富文本', '<script type=\"text/javascript\">\r\n                    $(function () {\r\n                        editormd.markdownToHTML(\"question-view\", {});\r\n                    });\r\n                </script>', 1566120985175, 1566120985175, 18, 0, 11, 0, 'javascript', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 0);
INSERT INTO `question` VALUES (53, 'SpringBoot笔记', '#Spring Boot\r\n\r\n##Spring boot 简介\r\n\r\n1. Spring boot是Spring家族中的一个全新的框架，它用来简化Spring应用程序的创建和开发过程，也可以说Spring boot能简化我们之前采用Spring mvc + Spring + MyBatis 框架进行开发的过程；\r\n\r\n2. 在以往我们采用 Spring mvc + Spring + MyBatis 框架进行开发的时候，搭建和整合三大框架，我们需要做很多工作，比如配置web.xml，配置Spring，配置MyBatis，并将它们整合在一起等，而Spring boot框架对此开发过程进行了革命性的颠覆，抛弃了繁琐的xml配置过程，采用大量的默认配置简化我们的开发过程；\r\n\r\n3. 所以采用Spring boot可以非常容易和快速地创建基于Spring 框架的应用程序，它让编码变简单了，配置变简单了，部署变简单了，监控变简单了；\r\n\r\n4. 正因为 Spring boot 它化繁为简，让开发变得极其简单和快速，所以在业界备受关注；\r\n\r\n5. Spring boot 在国内的关注趋势图：http://t.cn/ROQLquP\r\n\r\n   \r\n\r\n##Spring boot 的特性\r\n\r\n1. 能够快速创建基于Spring的应用程序；\r\n\r\n2. 能够直接使用java main方法启动内嵌的Tomcat, Jetty 服务器运行Spring boot程序，不需要部署war包文件；\r\n\r\n3. 提供约定的starter POM来简化Maven配置，让Maven的配置变得简单；\r\n\r\n4. 根据项目的Maven依赖配置，Spring boot自动配置Spring、Spring mvc等；\r\n\r\n5. 提供了程序的健康检查等功能；\r\n\r\n6. 基本可以完全不使用XML配置文件，采用注解配置；\r\n\r\n   \r\n\r\n##Spring boot 四大核心\r\n\r\n1. 自动配置：针对很多Spring应用程序和常见的应用功能，Spring Boot能自动提供相关配置；\r\n2. 起步依赖：告诉Spring Boot需要什么功能，它就能引入需要的依赖库；\r\n\r\n3. Actuator：让你能够深入运行中的Spring Boot应用程序，一探Spring boot程序的内部信息；\r\n\r\n4. 命令行界面：这是Spring Boot的可选特性，主要针对 Groovy 语言使用；\r\n\r\n\r\n\r\n##Spring boot 开发环境\r\n\r\n1. 推荐使用Spring boot最新版本，目前 Spring Boot 最新正式版为1.5.9.RELEASE；\r\n\r\n2. 如果是使用 eclipse，推荐安装 Spring Tool Suite (STS) 插件；\r\n\r\n3. 如果使用 IDEA 旗舰版，自带了Springboot插件；\r\n\r\n4. 推荐使用 Maven 3.2+，Maven目前最新版本为 3.5.2；\r\n\r\n5. 推荐使用 Java 8，虽然 Spring boot 也兼容 Java 6；\r\n\r\n   \r\n\r\n##第一个 Spring boot 程序\r\n\r\n1. 创建一个Spring boot项目；\r\n\r\n   - 可以采用方式一： 使用 eclipse 的 Spring Tool Suite (STS) 插件/或者 IDEA 自带的插件创建；\r\n\r\n   - 可以采用方式二：直接使用 Maven 创建项目的方式创建；\r\n\r\n2. 加入Spring boot 的父级和起步依赖；\r\n\r\n   - 父级依赖：\r\n\r\n   ```xml\r\n   <parent>\r\n       <groupId>org.springframework.boot</groupId>\r\n       <artifactId>spring-boot-starter-parent</artifactId>\r\n       <version>1.5.9.RELEASE</version>\r\n       <relativePath />\r\n   </parent>\r\n   ```\r\n\r\n   加入Spring boot父级依赖可以简化我们项目的Maven配置；\r\n\r\n   - 起步依赖：\r\n\r\n   ```xml\r\n   <dependency>\r\n       <groupId>org.springframework.boot</groupId>\r\n       <artifactId>spring-boot-starter-web</artifactId>\r\n   </dependency>\r\n   ```\r\n\r\n   加入Spring boot 的起步依赖也可以简化我们项目的Maven配置；\r\n\r\n3. 创建Spring boot 的入口main方法\r\n\r\n   ```java\r\n   @SpringBootApplication\r\n   public class SpringbootApplication {\r\n   	public static void main(String[] args) {\r\n   		SpringApplication.run(SpringbootApplication.class, args);\r\n   	}\r\n   }\r\n   ```\r\n\r\n4. 创建一个Spring mvc 的Controller\r\n\r\n   ```java\r\n   @Controller\r\n   public class HelloController {\r\n   	@RequestMapping(\"/sayHi\")\r\n   	public @ResponseBody String sayHi () {\r\n   		return \"Hi，Spring boot\";\r\n   	}\r\n   }\r\n   ```\r\n\r\n5. 运行Spring boot的入口main方法\r\n\r\n   通过eclipse、idea右键运行main方法；\r\n\r\n   至此，第一个Spring boot程序开发完成；\r\n\r\n   \r\n\r\n##第一个 Spring boot 程序解析\r\n\r\n1. Spring Boot 的父级依赖spring-boot-starter-parent配置之后，当前的项目就是Spring Boot项目；\r\n\r\n2. spring-boot-starter-parent是一个特殊的starter依赖，它用来提供相关的Maven默认依赖，使用它之后，常用的jar包依赖可以省去version配置；\r\n\r\n3. Spring Boot提供了哪些默认jar包的依赖，可查看该父级依赖的pom文件；\r\n\r\n4. 如果不想使用某个默认的依赖版本，可以通过pom.xml文件的属性配置覆盖各个依赖项，比如覆盖Spring版本：\r\n\r\n   ```\r\n   <properties>\r\n       <spring.version>5.0.0.RELEASE</spring.version>\r\n   </properties>\r\n   ```\r\n\r\n5. @SpringBootApplication 注解是Spring Boot项目的核心注解，主要作用是开启Spring自动配置；\r\n\r\n6. main方法是一个标准的Java程序的main方法，主要作用是作为项目启动运行的入口；\r\n\r\n7. @Controller 及 @ResponseBody 依然是我们之前的Spring mvc，因为Spring boot的里面依然是使用我们的Spring mvc + Spring + MyBatis 等框架；\r\n\r\n   \r\n\r\n##Spring boot 的核心配置文件\r\n\r\nSpring boot的核心配置文件用于配置Spring boot程序，有两种格式的配置文件：\r\n\r\n1. properties文件\r\n\r\n   键值对的properties属性文件配置方式\r\n\r\n   - 配置服务器端口：server.port=9800\r\n\r\n   - 配置应用访问路径：server.context-path=/13-springboot-web\r\n\r\n     \r\n\r\n2. yml文件\r\n\r\n   yml 是一种 yaml 格式的配置文件，主要采用一定的空格、换行等格式排版进行配置；\r\n\r\n   yaml 是一种直观的能够被计算机识别的的数据序列化格式，容易被人类阅读，yaml 类似于 xml，但是语法比 xml 简洁很多；\r\n\r\n   值与前面的冒号配置项必须要有一个空格；\r\n\r\n   yml 后缀也可以使用 yaml 后缀；\r\n\r\n   server:\r\n     port: 9091\r\n     context-path: /13-springboot-web\r\n\r\n\r\n\r\n3. 多环境配置文件\r\n\r\n   - 比如配置测试环境\r\n\r\n     spring.profiles.active=dev\r\n\r\n     application-dev.properties\r\n\r\n   - 比如配置生产环境\r\n\r\n     spring.profiles.active=product\r\n\r\n     application-product.properties\r\n\r\n     \r\n\r\n##Spring boot 自定义配置\r\n\r\n我们可以在Spring boot的核心配置文件中自定义配置，然后采用如下注解去读取配置的属性值；\r\n\r\n1. @Value注解\r\n\r\n   用于逐个读取自定义的配置，比如：\r\n\r\n   ```\r\n   @Value(\"${bjpowernode.name}\")\r\n   private String name;\r\n   ```\r\n\r\n2. @ConfigurationProperties\r\n\r\n   用于将整个文件映射成一个对象，比如：\r\n\r\n   ```\r\n   @Component\r\n   @ConfigurationProperties(prefix=\"bjpowernode\")\r\n   public class MyConfig {\r\n   	private String name;\r\n   	public String getName() {\r\n   		return name;\r\n   	}\r\n   	public void setName(String name) {\r\n   		this.name = name;\r\n   	}\r\n   }\r\n   ```\r\n\r\n\r\n\r\n##Spring boot 使用 JSP\r\n\r\n在Spring boot中使用jsp，按如下步骤进行：\r\n\r\n1. 在pom.xml文件中配置依赖项\r\n\r\n   ```xml\r\n   <!--引入Spring Boot内嵌的Tomcat对JSP的解析包-->\r\n   <dependency>\r\n       <groupId>org.apache.tomcat.embed</groupId>\r\n       <artifactId>tomcat-embed-jasper</artifactId>\r\n   </dependency>\r\n   \r\n   <!-- servlet依赖的jar包start -->\r\n   <dependency>\r\n   	<groupId>javax.servlet</groupId>\r\n   	<artifactId>javax.servlet-api</artifactId>\r\n   </dependency>\r\n   <!-- servlet依赖的jar包start -->\r\n   \r\n   <!-- jsp依赖jar包start -->\r\n   <dependency>\r\n   	<groupId>javax.servlet.jsp</groupId>\r\n   	<artifactId>javax.servlet.jsp-api</artifactId>\r\n   	<version>2.3.1</version>\r\n   </dependency>\r\n   <!-- jsp依赖jar包end -->\r\n   \r\n   <!--jstl标签依赖的jar包start -->\r\n   <dependency>\r\n   	<groupId>javax.servlet</groupId>\r\n   	<artifactId>jstl</artifactId>\r\n   </dependency>\r\n   <!--jstl标签依赖的jar包end -->\r\n   ```\r\n\r\n2. 在application.properties文件配置spring mvc的视图展示为jsp：\r\n\r\n   spring.mvc.view.prefix=/\r\n   spring.mvc.view.suffix=.jsp\r\n\r\n3. 在src/main 下创建一个webapp目录，然后在该目录下新建jsp页面\r\n\r\n   build中要配置备注中的配置信息\r\n\r\n   ```xml\r\n   <resources>\r\n     <resource>\r\n       <directory>src/main/java</directory>\r\n       <includes>\r\n         <include>**/*.xml</include>\r\n       </includes>\r\n     </resource>\r\n     <resource>\r\n       <directory>src/main/resources</directory>\r\n       <includes>\r\n         <include>**/*.*</include>\r\n       </includes>\r\n     </resource>\r\n     <resource>\r\n       <directory>src/main/webapp</directory>\r\n       <targetPath>META-INF/resources</targetPath>\r\n       <includes>\r\n         <include>**/*.*</include>\r\n       </includes>\r\n     </resource>\r\n   </resources>\r\n   ```\r\n\r\n   \r\n\r\n##Spring boot 集成 MyBatis\r\n\r\nSpring boot 集成 MyBatis的步骤如下：\r\n\r\n1. 在pom.xml中配置相关jar依赖；\r\n\r\n   ```xml\r\n   <!-- 加载mybatis整合springboot -->\r\n   <dependency>\r\n   	<groupId>org.mybatis.spring.boot</groupId>\r\n   	<artifactId>mybatis-spring-boot-starter</artifactId>\r\n   	<version>1.3.1</version>\r\n   </dependency>\r\n   \r\n   <!-- MySQL的jdbc驱动包 -->\r\n   <dependency>\r\n   	<groupId>mysql</groupId>\r\n   	<artifactId>mysql-connector-java</artifactId>\r\n   </dependency>\r\n   ```\r\n\r\n2. 在Springboot的核心配置文件 application.properties 中配置MyBatis的Mapper.xml文件所在位置：\r\n   mybatis.mapper-locations=classpath:com/bjpowernode/springboot/mapper/*.xml\r\n\r\n3. 在Springboot的核心配置文件application.properties中配置数据源：\r\n\r\n   ```properties\r\n   spring.datasource.username=root\r\n   spring.datasource.password=123456\r\n   spring.datasource.driver-class-name=com.mysql.jdbc.Driver\r\n   spring.datasource.url=?useUnicode=true&characterEncoding=utf8&useSSL=false\r\n   #mysql 8.0.11\r\n   spring.datasource.url=jdbc:mysql://localhost:3306/mp?useUnicode=true&characterEncoding=utf8&useSSL=false\r\n   spring.datasource.username=root\r\n   spring.datasource.password=xjh499954\r\n   spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver\r\n   ```\r\n\r\n4. 在MyBatis的Mapper接口中添加@Mapper注解 或者 \r\n   在运行的主类上添加 @MapperScan(\"com.bjpowernode.springboot.mapper\") 注解包扫描\r\n\r\n   \r\n\r\n##Spring boot 事务支持\r\n\r\nSpring Boot 使用事务非常简单；\r\n\r\n1. 在入口类中使用注解 @EnableTransactionManagement 开启事务支持；\r\n\r\n2. 在访问数据库的Service方法上添加注解 @Transactional 即可；\r\n\r\n   \r\n\r\n## Spring boot整合Email\r\n\r\n1. 在pom.xml中配置相关jar依赖；\r\n\r\n   ```xml\r\n   <!-- Java Mail -->\r\n   <dependency>\r\n       <groupId>org.springframework.boot</groupId>\r\n       <artifactId>spring-boot-starter-mail</artifactId>\r\n   </dependency>\r\n   ```\r\n\r\n2. 全局配置文件\r\n\r\n   ```properties\r\n   #邮箱服务器地址\r\n   spring.mail.host=smtp.qq.com\r\n   #发件人地址\r\n   spring.mail.username=1157418149@qq.com\r\n   #邮箱的授权码\r\n   spring.mail.password=fxhmhhousroshjic\r\n   spring.mail.default-encoding=utf-8\r\n   #发件人\r\n   mail.fromMail.addr=1157418149@qq.com\r\n   ```\r\n\r\n\r\n\r\n##Spring boot 实现 RESTfull API(REST风格，斗鱼房间号)\r\n\r\n1. 什么是RESTFull？\r\n\r\n   RESTFull 一种互联网软件架构设计的风格，但它并不是标准，它只是提出了一组客户端和服务器交互时的架构理念和设计原则，基于这种理念和原则设计的接口可以更简洁，更有层次；\r\n\r\n   任何的技术都可以实现这种理念；\r\n\r\n   比如我们要访问一个http接口：http://localhost:80080/api/order?id=1521&status=1\r\n\r\n   采用RESTFull风格则http地址为：http://localhost:80080/api/order/1021/1\r\n\r\n2. Spring boot开发RESTFull\r\n\r\n   Spring boot开发RESTFull 主要是几个注解实现：\r\n\r\n   - @PathVariable\r\n\r\n     获取url中的数据；\r\n\r\n     该注解是实现RESTFull最主要的一个注解；\r\n\r\n     ![image-20190715141724838](/Users/xjh/Library/Application Support/typora-user-images/image-20190715141724838.png)\r\n\r\n     ![image-20190715141922185](/Users/xjh/Library/Application Support/typora-user-images/image-20190715141922185.png)\r\n\r\n   - 增加 post方法（PostMapping）\r\n\r\n     接收和处理Post方式的请求；\r\n\r\n   - 删除 delete方法（DeleteMapping）\r\n\r\n     接收delete方式的请求，可以使用GetMapping代替；\r\n\r\n   - 修改 put方法（PutMapping）\r\n\r\n     接收put方式的请求，可以用PostMapping代替；\r\n\r\n   - 查询 get方法（GetMapping）\r\n\r\n     接收get方式的请求；\r\n\r\n   \r\n\r\n##Spring boot 热部署插件\r\n\r\n在实际开发中，我们修改某些代码逻辑功能或页面都需要重启应用，这无形中降低了开发效率；\r\n\r\n热部署是指当我们修改代码后，服务能自动重启加载新修改的内容，这样大大提高了我们开发的效率；\r\n\r\nSpring boot热部署通过添加一个插件实现；\r\n\r\n插件为：spring-boot-devtools，在Maven中配置如下：\r\n\r\n```xml\r\n<!-- springboot 开发自动热部署 -->\r\n<dependency>\r\n    <groupId>org.springframework.boot</groupId>\r\n    <artifactId>spring-boot-devtools</artifactId>\r\n    <optional>true</optional>\r\n</dependency>\r\n```\r\n\r\n该热部署插件在实际使用中会有一些小问题，明明已经重启，但没有生效，这种情况下，手动重启一下程序；\r\n\r\n\r\n\r\n##Spring boot 集成 Redis\r\n\r\nSpring boot 集成 Redis 的步骤如下：\r\n\r\n1. 在pom.xml中配置相关的jar依赖；\r\n\r\n   ```xml\r\n   <!-- 加载spring boot redis包 -->\r\n   <dependency>\r\n       <groupId>org.springframework.boot</groupId>\r\n       <artifactId>spring-boot-starter-data-redis</artifactId>\r\n   </dependency>\r\n   ```\r\n\r\n2. 在Springboot核心配置文件application.properties中配置redis连接信息：\r\n\r\n   ```properties\r\n   spring.redis.host=192.168.230.128\r\n   spring.redis.port=6379\r\n   spring.redis.password=123456\r\n   ```\r\n\r\n3. 配置了上面的步骤，Spring boot将自动配置RedisTemplate，在需要操作redis的类中注入redisTemplate;\r\n\r\n   在使用的类中注入：\r\n\r\n   ```java\r\n   @Autowired\r\n   private RedisTemplate<String, String> redisTemplate;\r\n   \r\n   @Autowired\r\n   private RedisTemplate<Object, Object> redisTemplate;\r\n   ```\r\n\r\n   ![image-20190715143954549](/Users/xjh/Library/Application Support/typora-user-images/image-20190715143954549.png)\r\n\r\n   4. 高并发缓存穿透问题解决（双重同步锁）\r\n\r\n      ![image-20190715145132311](/Users/xjh/Library/Application Support/typora-user-images/image-20190715145132311.png)\r\n\r\n   spring boot帮我们注入的redisTemplate类，泛型里面只能写 <String, String>、<Object, Object>\r\n\r\n   5. 哨兵模式redis集群配置：\r\n        redis:\r\n          password: 123456\r\n          sentinel:\r\n            master: mymaster \r\n            nodes: 192.168.179.128:26380,192.168.179.128:26382,192.168.179.128:26384\r\n\r\n   \r\n\r\n## SpringBoot整合RabbitMQ\r\n\r\n1. pom.xml中配置相关的jar依赖\r\n```xml\r\n<!-- RabbitMQ消息队列依赖 -->\r\n<dependency>\r\n    <groupId>org.springframework.boot</groupId>\r\n    <artifactId>spring-boot-starter-amqp</artifactId>\r\n</dependency>\r\n```\r\n2. 在Springboot核心配置文件application.properties中配置Rabbit连接信息\r\n```properties\r\n#对于rabbitMQ的支持\r\nspring.rabbitmq.host=127.0.0.1\r\nspring.rabbitmq.port=5672\r\nspring.rabbitmq.username=guest\r\nspring.rabbitmq.password=guest\r\n```\r\n\r\n3. \r\n\r\n##Spring boot 集成 Dubbo\r\n\r\n###集成前的准备\r\n\r\n1. 阿里巴巴提供的dubbo集成springboot开源项目；\r\n\r\n   https://github.com/alibaba\r\n\r\n2. 我们将采用该项目提供的jar包进行集成；\r\n\r\n   ```xml\r\n   <!--添加dubbo集成springboot依赖-->\r\n   <dependency>\r\n       <groupId>com.alibaba.spring.boot</groupId>\r\n       <artifactId>dubbo-spring-boot-starter</artifactId>\r\n       <version>1.0.0</version>\r\n   </dependency>\r\n   ```\r\n\r\n###正式集成\r\n\r\n开发Dubbo服务接口\r\n\r\n按照Dubbo官方开发建议，创建一个接口项目，该项目只定义接口和model类；\r\n\r\npublic interface UserService {\r\n    public String sayHi (String name);\r\n}\r\n\r\n###开发Dubbo服务提供者\r\n\r\n1、创建一个Springboot项目并配置好相关的依赖；\r\n\r\n2、加入springboot与dubbo集成的起步依赖：\r\n\r\n<dependency>\r\n    <groupId>com.alibaba.spring.boot</groupId>\r\n    <artifactId>dubbo-spring-boot-starter</artifactId>\r\n    <version>1.0.0</version>\r\n</dependency>\r\n\r\n3、在Springboot的核心配置文件application.properties中配置dubbo的信息：\r\n\r\nWEB服务端口\r\n\r\nserver.port=8080\r\n###dubbo配置\r\n\r\nspring.dubbo.appname=springboot-dubbo-provider\r\nspring.dubbo.registry=zookeeper://192.168.230.128:2181\r\n\r\n由于使用了zookeeper作为注册中心，则需要加入zookeeper的客户端jar包：\r\n\r\n<dependency>\r\n    <groupId>com.101tec</groupId>\r\n    <artifactId>zkclient</artifactId>\r\n    <version>0.10</version>\r\n</dependency>\r\n\r\n<!-- zookeeper客户端依赖start -->\r\n		<dependency>\r\n			<groupId>com.101tec</groupId>\r\n			<artifactId>zkclient</artifactId>\r\n			<version>0.10</version>\r\n			<exclusions>\r\n				<exclusion>\r\n					<groupId>log4j</groupId>\r\n					<artifactId>log4j</artifactId>\r\n				</exclusion>\r\n				<exclusion>\r\n					<groupId>org.slf4j</groupId>\r\n					<artifactId>slf4j-log4j12</artifactId>\r\n				</exclusion>\r\n			</exclusions>\r\n		</dependency>\r\n		<!-- zookeeper客户端依赖end -->\r\n\r\n4、编写Dubbo的接口实现类：\r\n\r\nimport org.springframework.stereotype.Component;\r\nimport com.alibaba.dubbo.config.annotation.Service;\r\nimport com.bjpowernode.springboot.dubbo.service.UserService;\r\n\r\n@Service(interfaceClass = UserService.class) //该注解是dubbo的\r\n@Component //该注解是spring的\r\npublic class UserServiceImpl implements UserService {\r\n	@Override\r\n	public String sayHi(String name) {\r\n		return \"Hi, \" + name;\r\n	}\r\n}\r\n\r\n5、编写一个入口main程序启动Dubbo服务提供者：\r\n\r\n@SpringBootApplication\r\n@EnableDubboConfiguration //开启dubbo配置支持\r\npublic class SpringbootApplication {\r\n	public static void main(String[] args) {\r\n		SpringApplication.run(SpringbootApplication.class, args);\r\n	}\r\n}\r\n\r\n###开发Dubbo服务消费者\r\n\r\n1、创建一个Springboot项目并配置好相关的依赖；\r\n\r\n2、加入springboot与dubbo集成的起步依赖：\r\n\r\n<dependency>\r\n    <groupId>com.alibaba.spring.boot</groupId>\r\n    <artifactId>dubbo-spring-boot-starter</artifactId>\r\n    <version>1.0.0</version>\r\n</dependency>\r\n\r\n3、在Springboot的核心配置文件application.properties中配置dubbo的信息：\r\n\r\nWEB服务端口\r\n\r\nserver.port=9090\r\n\r\ndubbo配置\r\n\r\nspring.dubbo.appname=springboot-dubbo-consumer\r\nspring.dubbo.registry=zookeeper://192.168.91.129:2181\r\n\r\n由于使用了zookeeper作为注册中心，则需要加入zookeeper的客户端jar包：\r\n\r\n<dependency>\r\n    <groupId>com.101tec</groupId>\r\n    <artifactId>zkclient</artifactId>\r\n    <version>0.10</version>\r\n</dependency>\r\n\r\n4、编写一个Controller类，调用远程的Dubbo服务：\r\n\r\n@Controller\r\npublic class UserController {\r\n	@Reference //使用dubbo的注解引用远程的dubbo服务\r\n	private UserService userService;\r\n	@RequestMapping(\"/sayHi\")\r\n	public @ResponseBody String sayHi () {\r\n		return userService.sayHi(\"spring boot dubbo......\");\r\n	}\r\n}\r\n\r\n5、编写一个入口main程序启动Dubbo服务提供者：\r\n\r\n@SpringBootApplication\r\n@EnableDubboConfiguration //开启dubbo配置支持\r\npublic class SpringbootApplication {\r\n	public static void main(String[] args) {\r\n		SpringApplication.run(SpringbootApplication.class, args);\r\n	}\r\n}\r\n\r\n##Spring boot 使用拦截器\r\n\r\n1. 按照Spring mvc的方式编写一个拦截器类,实现HandlerInterceptor接口，重点实现preHandle方法；\r\n\r\n2. 编写一个配置类实现WebMvcConfigurer\r\n\r\n   ```java\r\n   @Configuration\r\n   public class WebConfig implements WebMvcConfigurer {\r\n   \r\n       @Bean\r\n       public LoginInterceptor loginInterceptor(){\r\n           return new LoginInterceptor();\r\n       }\r\n   \r\n       String addPathPatterns[] = {\r\n   \r\n       };\r\n   \r\n       String excludePathPatterns[] = {\r\n           \"/redis/**\"\r\n       };\r\n   \r\n       @Override\r\n       public void addInterceptors(InterceptorRegistry registry) {\r\n           registry.addInterceptor(loginInterceptor())\r\n                   .addPathPatterns(addPathPatterns)\r\n                   .excludePathPatterns(excludePathPatterns);\r\n       }\r\n   }\r\n   ```\r\n\r\n\r\n\r\n##Spring boot 项目配置字符编码\r\n\r\n从springboot1.4.2之后开始新增的一种字符编码设置，在application.properties中设置；\r\n\r\n```properties\r\nspring.http.encoding.charset=UTF-8\r\nspring.http.encoding.enabled=true\r\nspring.http.encoding.force=true\r\n```\r\n\r\n\r\n\r\n## Spring boot 程序war包部署\r\n\r\n1. 程序入口类继承 SpringBootServletInitializer 类\r\n\r\n2. 程序入口类覆盖如下方法：\r\n\r\n   ```java\r\n   @Override\r\n   protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {\r\n       return application.sources(SpringbootApplication.class);\r\n   }\r\n   ```\r\n\r\n3. 更新包为war，在 pom.xml 中修改 <packaging>war</packaging>\r\n\r\n4. 配置springboot打包的插件\r\n\r\n```xml\r\n<!-- Springboot打包的插件 -->\r\n<plugin>\r\n    <groupId>org.springframework.boot</groupId>\r\n    <artifactId>spring-boot-maven-plugin</artifactId>\r\n</plugin>\r\n\r\n<resources>\r\n  <resource>\r\n    <directory>src/main/java</directory>\r\n    <includes>\r\n      <include>/*.xml</include>\r\n    </includes>\r\n  </resource>\r\n  <resource>\r\n    <directory>src/main/resources</directory>\r\n    <includes>\r\n      <include>/.</include>\r\n    </includes>\r\n  </resource>\r\n  <!-- 打包时将jsp文件拷贝到META-INF目录下 -->\r\n  <resource>\r\n    <!-- 指定resources插件处理哪个目录下的资源文件 -->\r\n    <directory>src/main/webapp</directory>\r\n    <!--注意此次必须要放在此目录下才能被访问到 -->\r\n    <targetPath>META-INF/resources</targetPath>\r\n    <includes>\r\n      <include>*/.*</include>\r\n    </includes>\r\n  </resource>\r\n</resources>\r\n```\r\n\r\n5. 在项目中通过 Maven install 在本地maven仓库安装成一个war包，然后将war包部署到tomcat下运行；\r\n\r\n   \r\n\r\n## Spring boot 程序打Jar包与运行\r\n\r\n1. Spring boot程序打包，在pom.xml文件加入如下Spring boot的maven插件：\r\n\r\n```xml\r\n<build>\r\n	<plugins>\r\n		<plugin>\r\n			<groupId>org.springframework.boot</groupId>\r\n			<artifactId>spring-boot-maven-plugin</artifactId>\r\n			<version>1.4.2.RELEASE</version>\r\n		</plugin>\r\n	</plugins>\r\n  \r\n	<resources>\r\n		<resource>\r\n			<directory>src/main/java</directory>\r\n			<includes>\r\n				<include>/*.xml</include>\r\n			</includes>\r\n		</resource>\r\n    \r\n		<resource>\r\n			<directory>src/main/resources</directory>\r\n			<includes>\r\n				<include>/.</include>\r\n			</includes>\r\n		</resource>\r\n    \r\n		<!-- 打包时将jsp文件拷贝到META-INF目录下 -->\r\n		<resource>\r\n			<!-- 指定resources插件处理哪个目录下的资源文件 -->\r\n			<directory>src/main/webapp</directory>\r\n			<!--注意此次必须要放在此目录下才能被访问到 -->\r\n			<targetPath>META-INF/resources</targetPath>\r\n			<includes>\r\n				<include>*/.*</include>\r\n			</includes>\r\n		</resource>\r\n    \r\n	</resources>\r\n</build>\r\n```\r\n\r\n2. 在项目中使用 Maven install 在本地maven仓库安装成一个jar；\r\n\r\n3. 使用java -jar xxx.jar 运行第2步生成的jar包，从而可以启动 Spring boot 程序；\r\n\r\n4. 访问第3步运行起来的 spring boot程序；\r\n\r\n   \r\n\r\n## Spring boot 部署与运行方式总结\r\n\r\n1. 在IDEA中直接运行spring boot程序的main方法（开发阶段）；\r\n\r\n2. 用maven将spring boot安装为一个jar包(内嵌tomcat)，使用Java命令运行：java -jar  spring-boot-xxx.jar \r\n   可以将该命令封装到一个Linux的一个shell脚本中（上线部署）\r\n\r\n   1. 写一个shell脚本：\r\n\r\n   ```shell\r\n   !/bin/sh\r\n   \r\n   java -jar xxx.jar\r\n   ```\r\n\r\n   2. 赋权限 chmod 777 run.sh\r\n\r\n   3. 启动shell脚本： ./run.sh\r\n\r\n3. 使用Spring boot的maven插件将Springboot程序打成war包，单独部署在tomcat中运行（上线部署）；\r\n\r\n   \r\n\r\n## spring boot 集成 Spring session\r\n\r\n1. 配置jar依赖\r\n\r\n```xml\r\n<dependency>\r\n    <groupId>org.springframework.session</groupId>\r\n    <artifactId>spring-session</artifactId>\r\n</dependency>\r\n\r\n<dependency>\r\n    <groupId>org.springframework.boot</groupId>\r\n    <artifactId>spring-boot-starter-data-redis</artifactId>\r\n</dependency>\r\n```\r\n\r\n2. 配置redis连接\r\n\r\n   ```properties\r\n   spring.redis.host=192.168.230.128\r\n   spring.redis.port=6379\r\n   spring.redis.password=123456\r\n   ```\r\n\r\n3. 在运行的主类上添加@EnableRedisHttpSession注解\r\n\r\n   或者在配置文件中加入：spring.session.store-type=redis\r\n\r\n## Spring boot 集成 Thymeleaf\r\n\r\n1、第一步：在Maven中引入Thymeleaf的依赖，加入以下依赖配置即可：\r\n\r\n<dependency>\r\n    <groupId>org.springframework.boot</groupId>\r\n    <artifactId>spring-boot-starter-thymeleaf</artifactId>\r\n</dependency>\r\n\r\n2、第二步：在Spring boot的核心配置文件application.properties中对Thymeleaf进行配置：\r\n\r\n开发阶段，建议关闭thymeleaf的缓存\r\n\r\nspring.thymeleaf.cache=false\r\n\r\n使用遗留的html5以去掉对html标签的校验\r\n\r\nspring.thymeleaf.mode=LEGACYHTML5\r\n\r\n在使用springboot的过程中，如果使用thymeleaf作为模板文件，则要求HTML格式必须为严格的html5格式，必须有结束标签，否则会报错；\r\n\r\n如果不想对标签进行严格的验证，使用spring.thymeleaf.mode=LEGACYHTML5去掉验证，去掉该验证，则需要引入如下依赖，否则会报错：\r\n\r\n<dependency>\r\n    <groupId>net.sourceforge.nekohtml</groupId>\r\n    <artifactId>nekohtml</artifactId>\r\n</dependency>\r\n\r\n<dependency>\r\n    <groupId>org.unbescape</groupId>\r\n    <artifactId>unbescape</artifactId>\r\n    <version>1.1.5.RELEASE</version>\r\n</dependency>\r\n\r\nNekoHTML是一个Java语言的 HTML扫描器和标签补全器 ,这个解析器能够扫描HTML文件并“修正”HTML文档中的常见错误。\r\nNekoHTML能增补缺失的父元素、自动用结束标签关闭相应的元素，修复不匹配的内嵌元素标签等；\r\n\r\n3、第三步：写一个Controller去映射到模板页面（和SpringMVC基本一致），比如：\r\n\r\n@RequestMapping(\"/index\")\r\npublic String index (Model model) {\r\n    model.addAttribute(\"data\", \"恭喜，Spring boot集成 Thymeleaf成功！\");\r\n    //return 中就是你页面的名字（不带.html后缀）\r\n    return \"index\";\r\n}\r\n\r\n4、第四步：在src/main/resources的templates下新建一个index.html页面用于展示数据：\r\n\r\nHTML页面的<html>元素中加入以下属性：<html xmlns:th=\"http://www.thymeleaf.org\">\r\n\r\n<!DOCTYPE html>\r\n<html xmlns:th=\"http://www.thymeleaf.org\">\r\n<head>\r\n<meta charset=\"UTF-8\"/>\r\n<title>Spring boot集成 Thymeleaf</title>\r\n</head>\r\n<body>\r\n<p th:text=\"${data}\">Spring boot集成 Thymeleaf</p>\r\n</body>\r\n</html>\r\n\r\nSpringboot使用thymeleaf作为视图展示，约定将模板文件放置在src/main/resource/templates目录下，静态资源放置在src/main/resource/static目录下\r\n\r\nThymeleaf 的标准表达式\r\n\r\nThymeleaf 的标准表达式主要有如下几类：\r\n\r\n1、标准变量表达式\r\n\r\n语法：${...}\r\n\r\n变量表达式用于访问容器（tomcat）上下文环境中的变量，功能和 JSTL 中的 ${} 相同；\r\n\r\nThymeleaf 中的变量表达式使用 ${变量名} 的方式获取其中的数据\r\n\r\n比如在Spring mvc 的 Controllar中使用model.addAttribute向前端传输数据，代码如下：\r\n\r\n\r\n2、选择变量表达式\r\n\r\n语法：*{...}\r\n\r\n选择变量表达式，也叫星号变量表达式，使用 th:object 属性来绑定对象，比如：\r\n\r\n@RequestMapping(value=\"/userinfo\")\r\npublic String userinfo (Model model) {\r\n    User user = new User();\r\n    user.setId(1);\r\n    user.setNick(\"昵称\");\r\n    user.setPhone(\"13700020000\");\r\n    user.setAddress(\"北京大兴\");\r\n    model.addAttribute(\"user\", user);\r\n    model.addAttribute(\"hello\", \"helloworld\");\r\n    return \"user\";\r\n}\r\n\r\n前端接收代码\r\n\r\n<div th:object=\"${user}\" >\r\n    <p>nick: <span th:text=\"*{nick}\">张</span></p>\r\n    <p>phone: <span th:text=\"*{phone}\" >三</span></p>\r\n    <p>email: <span th:text=\"*{email}\" >北京</span></p>\r\n    <p>address: <span th:text=\"*{address}\" >北京</span></p>\r\n</div>\r\n\r\n选择表达式首先使用th:object来邦定后台传来的User对象，然后使用 * 来代表这个对象，后面 {} 中的值是此对象中的属性；\r\n\r\n选择变量表达式 *{...} 是另一种类似于变量表达式 ${...} 表示变量的方法；\r\n\r\n选择变量表达式在执行时是在选择的对象上求解，而${...}是在上下文的变量Model上求解；\r\n\r\n通过 th:object 属性指明选择变量表达式的求解对象；\r\n\r\n上述代码等价于：\r\n\r\n<div>\r\n    <p>nick: <span th:text=\"${user.nick}\">张</span></p>\r\n    <p>phone: <span th:text=\"${user.phone}\" >三</span></p>\r\n    <p>email: <span th:text=\"${user.email}\" >北京</span></p>\r\n    <p>address: <span th:text=\"${user.address}\" >北京</span></p>\r\n</div>\r\n\r\n标准变量表达式和选择变量表达式可以混合一起使用，比如：\r\n\r\n<div th:object=\"${user}\" >\r\n    <p>nick: <span th:text=\"*{nick}\">张</span></p>\r\n    <p>phone: <span th:text=\"${user.phone}\" >三</span></p>\r\n    <p>email: <span th:text=\"${user.email}\" >北京</span></p>\r\n    <p>address: <span th:text=\"*{address}\" >北京</span></p>\r\n</div>\r\n\r\n也可以不使用 th:object 进行对象的选择，而直接使用 *{...} 获取数据，比如：\r\n\r\n<div>\r\n    <p>nick: <span th:text=\"*{user.nick}\">张</span></p>\r\n    <p>phone: <span th:text=\"*{user.phone}\" >三</span></p>\r\n    <p>email: <span th:text=\"*{user.email}\" >北京</span></p>\r\n    <p>address: <span th:text=\"*{user.address}\" >北京</span></p>\r\n</div>\r\n\r\n3、URL表达式\r\n\r\n语法：@{...}\r\n\r\nURL表达式可用于 <script src=\"...\">、<link href=\"...\">、<a href=\"...\">等\r\n\r\n1、绝对URL，比如： \r\n\r\n<a href=\"info.html\" th:href=\"@{\'http://localhost:8080/boot/user/info?id=\'+${user.id}}\">查看</a>\r\n\r\n2、相对URL，相对于页面，比如：\r\n\r\n<a href=\"info.html\" th:href=\"@{\'user/info?id=\'+${user.id}}\">查看</a>\r\n\r\n3、相对URL，相对于项目上下文，比如：\r\n\r\n<a href=\"info.html\" th:href=\"@{\'/user/info?id=\'+${user.id}}\">查看</a> （项目的上下文名会被自动添加）\r\n\r\nThymeleaf 的常见属性\r\n\r\n如下为thymeleaf的常见属性：\r\n\r\nth:action\r\n\r\n定义后台控制器的路径，类似<form>标签的action属性，比如：\r\n\r\n<form id=\"login\" th:action=\"@{/login}\">......</form>\r\nth:each\r\n\r\n 这个属性非常常用，比如从后台传来一个对象集合那么就可以使用此属性遍历输出，它与JSTL中的<c: forEach>类似，此属性既可以循环遍历集合，也可以循环遍历数组及Map，比如：\r\n\r\n<tr th:each=\"user, interStat : ${userlist}\">\r\n    <td th:text=\"${interStat.index}\"></td>\r\n    <td th:text=\"${user.id}\"></td>\r\n    <td th:text=\"${user.nick}\"></td>\r\n    <td th:text=\"${user.phone}\"></td>\r\n    <td th:text=\"${user.email}\"></td>\r\n    <td th:text=\"${user.address}\"></td>\r\n</tr>\r\n\r\n以上代码解读如下：\r\n\r\nth:each=\"user, iterStat : ${userlist}\" 中的 ${userList} 是后台传来的Key，\r\nuser是${userList} 中的一个数据，\r\niterStat 是 ${userList} 循环体的信息，\r\n其中user及iterStat自己可以随便写；\r\n\r\ninterStat是循环体的信息，通过该变量可以获取如下信息：\r\n\r\nindex、size、count、even、odd、first、last，其含义如下：\r\n\r\nindex: 当前迭代对象的index（从0开始计算）\r\ncount: 当前迭代对象的个数（从1开始计算）\r\nsize: 被迭代对象的大小\r\ncurrent: 当前迭代变量\r\neven/odd: 布尔值，当前循环是否是偶数/奇数（从0开始计算）\r\nfirst: 布尔值，当前循环是否是第一个\r\nlast: 布尔值，当前循环是否是最后一个\r\n\r\n注意：循环体信息interStat也可以不定义，则默认采用迭代变量加上Stat后缀，即userStat\r\n\r\nMap类型的循环：  \r\n\r\n<div th:each=\"myMapVal : ${myMap}\">\r\n    <span th:text=\"${myMapVal.key}\"></span>\r\n    <span th:text=\"${myMapVal.value}\"></span>\r\n    <br/>\r\n</div>\r\n\r\n${myMapVal.key} 是获取map中的key，${myMapVal.value} 是获取map中的value；\r\n\r\n数组类型的循环：  \r\n\r\n<div th:each=\"myArrayVal : ${myArray}\">\r\n    <div th:text=\"${myArrayVal}\"></div>\r\n</div> \r\n\r\nth:href\r\n\r\n 定义超链接，比如：\r\n\r\n<a  class=\"login\" th:href=\"@{/login}\">登录</a>\r\n\r\nth:id\r\n\r\n类似html标签中的id属性，比如：\r\n\r\n<span th:id=\"${hello}\">aaa</span>\r\n\r\nth:if\r\n\r\n条件判断，比如后台传来一个变量，判断该变量的值，1为男，2为女：\r\n\r\n<span th:if=\"${sex} == 1\" >\r\n	男：<input type=\"radio\" name=\"se\"  th:value=\"男\" />\r\n</span>\r\n<span th:if=\"${sex} == 2\">\r\n	女：<input type=\"radio\" name=\"se\" th:value=\"女\"  />\r\n</span>\r\n\r\nth:unless\r\n\r\nth:unless是th:if的一个相反操作，上面的例子可以改写为：\r\n\r\n<span th:unless=\"${sex} == 1\" >\r\n	女：<input type=\"radio\" name=\"se\"  th:value=\"女\" />\r\n</span>\r\n<span th:unless=\"${sex} == 2\">\r\n	男：<input type=\"radio\" name=\"se\" th:value=\"男\"  />\r\n</span>\r\n\r\nth:switch/th:case\r\n\r\nswitch，case判断语句，比如：\r\n\r\n<div th:switch=\"${sex}\">\r\n  <p th:case=\"1\">性别：男</p>\r\n  <p th:case=\"2\">性别：女</p>\r\n  <p th:case=\"*\">性别：未知</p>\r\n</div>\r\n\r\n一旦某个case判断值为true，剩余的case则都当做false，“*”表示默认的case，前面的case都不匹配时候，执行默认的case；\r\n\r\nth:object\r\n\r\n用于数据对象绑定\r\n\r\n通常用于选择变量表达式（星号表达式）\r\n\r\nth:src\r\n\r\n用于外部资源引入，比如<script>标签的src属性，<img>标签的src属性，常与@{}表达式结合使用；\r\n\r\n<script th:src=\"@{/static/js/jquery-2.4.min.js}\"></script>\r\n<img th:src=\"@{/static/image/logo.png}\"/>\r\n\r\nth:text\r\n\r\n用于文本的显示，比如：\r\n\r\n<input type=\"text\" id=\"realName\" name=\"reaName\" th:text=\"${realName}\">\r\n\r\nth:value\r\n\r\n类似html标签中的value属性，能对某元素的value属性进行赋值，比如：\r\n\r\n<input type=\"hidden\" id=\"userId\" name=\"userId\" th:value=\"${userId}\">\r\n\r\nth:attr\r\n\r\n该属性也是用于给HTML中某元素的某属性赋值，但该方式写法不够优雅，比如上面的例子可以写成如下形式：\r\n\r\n<input type=\"hidden\" id=\"userId\" name=\"userId\" th:attr=\"value=${userId}\" >\r\n\r\nThymeleaf 字面量\r\n\r\n文本字面量\r\n\r\n用单引号\'...\'包围的字符串为文本字面量，比如：\r\n\r\n<a th:href=\"@{\'api/getUser?id=\' + ${user.id}}\">修改</a>\r\n\r\n数字字面量\r\n\r\n<p>今年是<span th:text=\"2017\">1949</span>年</p>\r\n<p>20年后, 将是<span th:text=\"2017 + 20\">1969</span>年</p>\r\nboolean字面量\r\n\r\ntrue和false\r\n\r\n<p th:if=\"${isFlag} == false\">\r\nfalse在花括号外面，解析识别由Thymleaf自身完成\r\n</p>\r\n\r\n<p th:if=\"${isFlag == true}\">\r\nfalse写在花括号里面，解析识别由SpringEL完成\r\n</p>\r\n\r\nnull字面量\r\n\r\n<p th:if=\"${userlist == null}\">\r\nuserlist为空\r\n</p>\r\n\r\n<p th:if=\"${userlist != null}\">\r\nuserlist不为空\r\n</p>\r\n\r\nThymeleaf 字符串拼接\r\n\r\n一种是字面量拼接：\r\n\r\n<a href=\"#\" th:text=\"\'第\'+${sex}+\'页 ,共\'+${sex}+\'页\'\"></a>\r\n\r\n另一种更优雅的方式，使用“|”减少了字符串的拼接：\r\n\r\n<a href=\"#\" th:text=\"|第${sex}页，共${sex}页|\"></a>\r\n\r\nThymeleaf 三元运算判断\r\n\r\n<span th:text=\"${sex eq \'1\'} ? \'男\' : \'女\'\">未知</span>\r\n\r\nThymeleaf 运算和关系判断\r\n\r\n算术运算：+ , - , * , / , %\r\n\r\n关系比较: > , < , >= , <= ( gt , lt , ge , le )\r\n\r\n相等判断：== , != ( eq , ne )\r\n\r\nThymaleaf 表达式基本对象\r\n\r\n1、模板引擎提供了一组内置的对象，这些内置的对象可以直接在模板中使用，这些对象由#号开始引用：\r\n\r\n2、官方手册：http://t.cn/RHsbZpk\r\n\r\nctx：上下文对象\r\n\r\nvars：上下文变量\r\n\r\nlocale: 上下文语言环境.\r\n\r\nhttpServletRequest： (仅在web上下文)相当于HttpServletRequest 对象，这是2.x版本，若是3.x版本使用 #request；\r\n\r\nhttpSession： (仅在web上下文)相当于HttpSession 对象，这是2.x版本，若是3.x版本使用#session； 需要在后台controller中设置了session\r\n\r\nThymaleaf 表达式功能对象\r\n\r\n1、模板引擎提供的一组功能性内置对象，可以在模板中直接使用这些对象提供的功能方法：\r\n\r\n2、工作中常使用的数据类型，如集合，时间，数值，可以使用thymeleaf的提供的功能性对象来解析他们；\r\n\r\n3、内置功能对象前都需要加#号，内置对象一般都以s结尾；\r\n\r\n4、官方手册：http://t.cn/RHs5O6z\r\n\r\ndates: java.util.Date对象的实用方法，<span th:text=\"${#dates.format(curDate, \'yyyy-MM-dd HH:mm:ss\')}\"></span>\r\n\r\ncalendars: 和dates类似, 但是 java.util.Calendar 对象；\r\n\r\nnumbers: 格式化数字对象的实用方法；\r\n\r\nstrings: 字符串对象的实用方法： contains, startsWith, prepending/appending等；\r\n\r\nobjects: 对objects操作的实用方法；\r\n\r\nbools: 对布尔值求值的实用方法；\r\n\r\narrays: 数组的实用方法；\r\n\r\nlists: list的实用方法，比如<span th:text=\"${#lists.size(datas)}\"></span>\r\n\r\nsets: set的实用方法；\r\n\r\nmaps: map的实用方法；\r\n\r\naggregates: 对数组或集合创建聚合的实用方法；\r\n\r\nThymeleaf 在 SpringBoot 中的配置大全：\r\n\r\nThymeleaf的配置文件说明：\r\n\r\nspring.thymeleaf.cache = true ＃启用模板缓存。\r\n\r\nspring.thymeleaf.check-template = true ＃在呈现模板之前检查模板是否存在。\r\n\r\nspring.thymeleaf.check-template-location = true ＃检查模板位置是否存在。\r\n\r\nspring.thymeleaf.content-type = text/html ＃Content-Type值。\r\n\r\nspring.thymeleaf.enabled = true ＃启用MVC Thymeleaf视图解析。\r\n\r\nspring.thymeleaf.encoding = UTF-8 ＃模板编码。\r\n\r\nspring.thymeleaf.excluded-view-names = ＃应该从解决方案中排除的视图名称的逗号分隔列表。\r\n\r\nspring.thymeleaf.mode = HTML5 ＃应用于模板的模板模式。另请参见StandardTemplateModeHandlers。\r\n\r\nspring.thymeleaf.prefix = classpath:/templates/ ＃在构建URL时预先查看名称的前缀。\r\n\r\nspring.thymeleaf.suffix = .html ＃构建URL时附加到查看名称的后缀。\r\n\r\nspring.thymeleaf.template-resolver-order = ＃链中模板解析器的顺序。\r\n\r\nspring.thymeleaf.view-names = ＃可以解析的视图名称的逗号分隔列表。\r\n\r\n\r\n\r\n## Spring boot Actuator\r\n\r\n在生产环境中，需要实时或定期监控服务的可用性，spring-boot 的 actuator 功能提供了很多监控所需的接口。\r\n\r\nactuator是spring boot提供的对应用系统的自省和监控的集成功能，可以对应用系统进行配置查看、相关功能统计等；\r\n\r\n1. 在项目的Maven中添加如下依赖：\r\n\r\n   ```xml\r\n   <dependency>  \r\n       <groupId>org.springframework.boot</groupId>  \r\n       <artifactId>spring-boot-starter-actuator</artifactId>  \r\n   </dependency>  \r\n   ```\r\n\r\n2. application.properties 或 application.yml 配置文件中指定监控的HTTP端口；\r\n\r\n如果不指定，则使用和server相同的端口，比如：\r\n\r\n服务运行的端口\r\n\r\nserver.port=8100\r\n\r\nactuator监控的端口（端口可配可不配）\r\n\r\nmanagement.port=8080\r\n\r\n关闭安全鉴权\r\n\r\nmanagement.security.enabled=false\r\n\r\n访问举例：http://localhost:8080/actuator/health\r\n\r\nactuator 提供的主要功能：\r\n\r\n| HTTP方法 |      路径       |            描述            | 鉴权  |\r\n| :------: | :-------------: | :------------------------: | :---: |\r\n|   GET    |   /autoconfig   |   查看自动配置的使用情况   | true  |\r\n|   GET    |  /configprops   | 查看配置属性，包括默认配置 | true  |\r\n|   GET    |     /beans      |    查看bean及其关系列表    | true  |\r\n|   GET    |      /dump      |         打印线程栈         | true  |\r\n|   GET    |      /env       |      查看所有环境变量      | true  |\r\n|   GET    |   /env/{name}   |       查看具体变量值       | true  |\r\n|   GET    |     /health     |      查看应用健康指标      | false |\r\n|   GET    |      /info      |        查看应用信息        | false |\r\n|   GET    |    /mappings    |      查看所有url映射       | true  |\r\n|   GET    |    /metrics     |      查看应用基本指标      | true  |\r\n|   GET    | /metrics/{name} |        查看具体指标        | true  |\r\n|   GET    |     /trace      |      查看基本追踪信息      | true  |\r\n|   POST   |    /shutdown    |          关闭应用          | true  |\r\n\r\n\r\n\r\n其中：\r\n\r\n1、/info 需要自己在application.properties配置文件中添加信息：\r\n\r\ninfo.contact.email=bjpowernode@163.com\r\ninfo.contact.phone=010-84846003\r\n\r\n然后请求才会有数据；\r\n\r\n2、/shutdown 需要在配置文件中开启才能生效：\r\n\r\nendpoints.shutdown.enabled=true\r\n\r\n3、/trace 记录最近100个请求的信息；\r\n\r\n\r\n\r\n## Spring boot 综合案例\r\n\r\n采用 Springboot + dubbo + mybatis + redis + Thymeleaf 实现对数据库的增删改查以及缓存操作； \r\n\r\n后端使用 spring boot + dubbo + mybatis + redis 实现对数据库数据的增删改查以及缓存操作；\r\n\r\n查询数据后将数据放入redis缓存中，减少对数据库的直接访问；\r\n\r\n\r\n\r\n\r\n', 1566124213900, 1566124213900, 20, 0, 37, 0, 'java,spring,redis', 'https://avatars3.githubusercontent.com/u/57940966?v=4', 1);
INSERT INTO `question` VALUES (54, '最热话题实现测试', '最热，七天最热，30天最热', 1573987279000, 1573987279000, 18, 0, 160, 0, 'java', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 0);
INSERT INTO `question` VALUES (55, 'MyBatis中@parm注解的使用时机和需要注意什么', '1. 传递单个参数非JavaBean，为什么必须需要注解\r\n2. 传递单个参数为JavaBean，可以不加@parm注解\r\n', 1581155058746, 1581155058746, 18, 1, 140, 0, 'java,mybatis', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 1);
COMMIT;

-- ----------------------------
-- Table structure for report
-- ----------------------------
DROP TABLE IF EXISTS `report`;
CREATE TABLE `report` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `question_id` int(11) NOT NULL,
  `question_title` varchar(255) COLLATE utf8_bin NOT NULL,
  `report_type` varchar(20) COLLATE utf8_bin NOT NULL,
  `report_details` varchar(100) COLLATE utf8_bin NOT NULL,
  `report_creator` int(11) DEFAULT NULL,
  `report_user` varchar(30) COLLATE utf8_bin DEFAULT NULL,
  `gmt_create` bigint(255) NOT NULL,
  `report_status` int(1) unsigned zerofill NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

-- ----------------------------
-- Records of report
-- ----------------------------
BEGIN;
INSERT INTO `report` VALUES (1, 55, 'MyBatis中@parm注解的使用时机和需要注意什么', '低俗色情', '测试举报', 18, 'seagold', 1581407358815, 1);
INSERT INTO `report` VALUES (2, 56, '标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题av标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题av标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题a标题av', '1', '1111ash1111ash1111ash', 1, '1', 1581408358800, 2);
COMMIT;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `account_id` varchar(100) COLLATE utf8_bin DEFAULT NULL,
  `name` varchar(50) COLLATE utf8_bin DEFAULT NULL,
  `token` char(36) COLLATE utf8_bin DEFAULT NULL,
  `head_img` varchar(255) COLLATE utf8_bin DEFAULT NULL,
  `status` int(1) unsigned zerofill NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

-- ----------------------------
-- Records of user
-- ----------------------------
BEGIN;
INSERT INTO `user` VALUES (18, '49060515', 'seagold', '1ad8ff17-b9c3-464c-a8ef-9f9703453473', 'https://avatars2.githubusercontent.com/u/49060515?v=4', 1);
INSERT INTO `user` VALUES (20, '57940966', 'Thanos', 'b4860081-884a-4e1f-af96-64a1e4c6e7d4', 'https://avatars3.githubusercontent.com/u/57940966?v=4', 1);
INSERT INTO `user` VALUES (21, '5157063963', 'thebsii', 'f0846574-42f5-4a64-bd83-9c669c52cd7a', 'https://tvax4.sinaimg.cn/crop.0.0.667.667.50/005D0vV1ly8g5o1yho9bmj30ij0ijq3j.jpg?KID=imgbed,tva&Expires=1581504581&ssig=yowTg5max%2F', 0);
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;
